﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Threading;
using System.Threading.Tasks;

namespace ImageGallery
{
    class GestureRecognition
    {
        private static PXCMGesture.Gesture.Label lastEvent = PXCMGesture.Gesture.Label.LABEL_ANY;
        private DateTime lastEventTime = DateTime.Now;

        private static Boolean flags = new Boolean();
        private PXCMSession session = null;
        private MainWindow wpfWindow;
        private bool disconnected = false;
        private PXCMGesture.GeoNode[][] nodes = new PXCMGesture.GeoNode[2][] { new PXCMGesture.GeoNode[11], new PXCMGesture.GeoNode[11] };
        private PXCMGesture.Gesture[] gestures = new PXCMGesture.Gesture[2];

        public GestureRecognition(MainWindow window)
        {
            this.wpfWindow = window;
            pxcmStatus sts = PXCMSession.CreateInstance(out session);
        }

        private bool DisplayDeviceConnection(bool state)
        {
            if (state)
            {
                if (!disconnected) MessageBox.Show("Device Disconnected");
                disconnected = true;
            }
            else
            {
                if (disconnected) MessageBox.Show("Device Reconnected");
                disconnected = false;
            }
            return disconnected;
        }

        //private void DisplayGesture(PXCMGesture gesture)
        //{
        //    gesture.QueryGestureData(0, PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_PRIMARY, 0, out gestures[0]);
        //    DisplayGestures(gestures);

        //    //gesture.QueryNodeData(0, PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_PRIMARY, nodes[0]);
        //    //DisplayNode(nodes);
        //}

        //private void DisplayNode(PXCMGesture.GeoNode[][] nodes)
        //{
        //    if (nodes == null) return;

        //    if (nodes[0][0].massCenterImage.x > currentX + 50 )
        //    {
        //        currentX = nodes[0][0].massCenterImage.x;
        //        Task t = new Task(() =>
        //        {
        //            VoiceSynthesis.Speak(wpfWindow.getModule(), 0, "plus");
        //        });

        //        t.Start();
        //        t.Wait();
        //        return;
        //    }
        //    else if (nodes[0][0].massCenterImage.x < currentX - 50)
        //    {
        //        currentX = nodes[0][0].massCenterImage.x;
        //        Task t = new Task(() =>
        //        {
        //            VoiceSynthesis.Speak(wpfWindow.getModule(), 0, "minus");
        //        });
        //        t.Start();
        //        t.Wait();
        //        return;
        //    }
        //}

        public void SimplePipeline()
        {
            bool sts = true;
            UtilMPipeline pp = null;
            disconnected = false;

            pp = new UtilMPipeline();
            pp.QueryCapture().SetFilter(GetCheckedDevice());

            pp.EnableGesture(GetCheckedModule());

            if (pp.Init())
            {
                while (true)
                {
                    if (!pp.AcquireFrame(true)) break;
                    if (!DisplayDeviceConnection(pp.IsDisconnected()))
                    {
                        // added using to dispose gesture object.
                        using (PXCMGesture gesture = pp.QueryGesture())
                        {
                           // DisplayGesture(gesture);
                            gesture.QueryGestureData(0, PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_PRIMARY, 0, out gestures[0]);
                            if (lastEvent == gestures[0].label && (lastEventTime.AddSeconds(2) > DateTime.Now))
                            {
                                pp.ReleaseFrame();
                                continue;
                            }

                            DisplayGestures(gestures);
                        }
                    }
                    pp.ReleaseFrame();
                }
            }
            else
            {
                MessageBox.Show("Init Failed");
                sts = false;
            }

            pp.Close();
            pp.Dispose();
            session.Dispose();
            if (sts) MessageBox.Show("Stopped");
        }

        private string GetCheckedDevice()
        {
            PXCMSession.ImplDesc desc = new PXCMSession.ImplDesc();
            desc.group = PXCMSession.ImplGroup.IMPL_GROUP_SENSOR;
            desc.subgroup = PXCMSession.ImplSubgroup.IMPL_SUBGROUP_VIDEO_CAPTURE;

            for (uint i = 0; ; i++)
            {
                PXCMSession.ImplDesc desc1;
                if (session.QueryImpl(ref desc, i, out desc1) < pxcmStatus.PXCM_STATUS_NO_ERROR) break;
                PXCMCapture capture;
                if (session.CreateImpl<PXCMCapture>(ref desc1, PXCMCapture.CUID, out capture) < pxcmStatus.PXCM_STATUS_NO_ERROR) continue;
                for (uint j = 0; ; j++)
                {
                    PXCMCapture.DeviceInfo dinfo;
                    if (capture.QueryDevice(j, out dinfo) < pxcmStatus.PXCM_STATUS_NO_ERROR) break;
                    return dinfo.name.get();
                }
                capture.Dispose();
            }

            return string.Empty;
        }

        private string GetCheckedModule()
        {
            PXCMSession.ImplDesc desc = new PXCMSession.ImplDesc();
            desc.cuids[0] = PXCMGesture.CUID;

            for (uint i = 0; ; i++)
            {
                PXCMSession.ImplDesc desc1;
                if (session.QueryImpl(ref desc, i, out desc1) < pxcmStatus.PXCM_STATUS_NO_ERROR) break;

                return desc1.friendlyName.get();
            }

            return string.Empty;
        }

        private void DisplayGestures(PXCMGesture.Gesture[] gesture)
        {
            if (gesture != null && gesture[0].label > 0)
            {
                switch (gesture[0].label)
                {
                    case PXCMGesture.Gesture.Label.LABEL_ANY:
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_HAND_CIRCLE:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() => 
                            { 
                                wpfWindow.RotatePhoto();
                                lastEvent = PXCMGesture.Gesture.Label.LABEL_HAND_CIRCLE;
                                lastEventTime = DateTime.Now;
                            }));
                            flags = false;
                        }
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_HAND_WAVE:
                        if (flags == false && this.wpfWindow.isSinglePhoto)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                            {
                                wpfWindow.slideShow();
                                lastEvent = PXCMGesture.Gesture.Label.LABEL_HAND_WAVE;
                                lastEventTime = DateTime.Now;
                            }));
                            flags = false;
                        }
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_MASK_DETAILS:
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_MASK_SET:
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_DOWN:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                                {
                                    wpfWindow.SetNextFolderPath(1);
                                    lastEvent = PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_DOWN;
                                    lastEventTime = DateTime.Now;
                                }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_LEFT:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                            {
                                wpfWindow.NextPhotos();
                                lastEvent = PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_LEFT;
                                lastEventTime = DateTime.Now;
                            }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_RIGHT:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                            {
                                wpfWindow.PreviousPhoto();
                                lastEvent = PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_RIGHT;
                                lastEventTime = DateTime.Now;
                            }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_UP:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                              {
                                  wpfWindow.SetNextFolderPath(-1);
                                  lastEvent = PXCMGesture.Gesture.Label.LABEL_NAV_SWIPE_UP;
                                  lastEventTime = DateTime.Now;
                              }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_POSE_BIG5:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                            {
                                wpfWindow.togglePhotoDisplay();
                                lastEvent = PXCMGesture.Gesture.Label.LABEL_POSE_BIG5;
                                lastEventTime = DateTime.Now;
                            }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_POSE_PEACE:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                                {
                                    wpfWindow.LoadBookmarks(0);
                                    lastEvent = PXCMGesture.Gesture.Label.LABEL_POSE_PEACE;
                                    lastEventTime = DateTime.Now;                                                           
                                    this.wpfWindow.myAsyncTask = Task.Factory.StartNew(() => VoiceSynthesis.Speak(wpfWindow.getModule(), 0, "Your favourite photos are loaded."));
                                }));
                            flags = false;
                        }
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_POSE_THUMB_DOWN:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                           {
                               wpfWindow.unSaveBookmark();
                               lastEvent = PXCMGesture.Gesture.Label.LABEL_POSE_THUMB_DOWN;
                               lastEventTime = DateTime.Now;
                           }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_POSE_THUMB_UP:
                        if (flags == false)
                        {
                            flags = true;
                            wpfWindow.Dispatcher.Invoke(new Action(() =>
                            {
                                wpfWindow.SaveToBookmark();
                                lastEvent = PXCMGesture.Gesture.Label.LABEL_POSE_THUMB_UP;
                                lastEventTime = DateTime.Now;
                            }));
                            flags = false;
                        }
                        break;

                    case PXCMGesture.Gesture.Label.LABEL_SET_CUSTOMIZED:
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_SET_HAND:
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_SET_NAVIGATION:
                        break;
                    case PXCMGesture.Gesture.Label.LABEL_SET_POSE:
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
